import re
import os
import time
from collections import Counter
from datetime import datetime

import asyncio
from asyncio import Semaphore
from asgiref.sync import sync_to_async

import pandas as pd
import requests
from aiogram import F, types
# from app.keyboards import main_kb, inspection_kb, completion, data_conteiner, start_kb
# from utilites.utilits_bot import coincidence
from aiogram import Router
from aiogram.fsm.context import FSMContext
# from models import get_users, init, get_user, create_user, create_conteiner, get_first_conteiner, ImagesConteiner, get_conteiner, StatusConteiner
from aiogram.types import Message, InlineKeyboardMarkup, InlineKeyboardButton
from icecream import ic

import http_rest
from app.keyboards import tech_actions, select_jurnal, ref_jr_control, js_ref_temp, js_ref_opt
from form.forms import Jrnal
from start_bot import AUTHORS, process_bac, jason_save
from utilites.bot_util import curent_date

# from form.forms import Form, Stat

router = Router()
semaphore = Semaphore(5)
back_gps_key = None

async def canceling2(message: Message, state: FSMContext):
    if message.text == 'Отмена заявки':
        await message.delete()
        await state.clear()
        await message.answer('Выберите действие', reply_markup=tech_actions)
    elif message.text == 'Отмена':
        await message.delete()
        await state.clear()
        await message.answer('Выберите действие', reply_markup=tech_actions)
    elif message.text == 'Главное меню':
        await message.delete()
        await state.clear()
        await message.answer('Выберите действие', reply_markup=tech_actions)
    else:
        return True


# async def text_to_new_jurn():
#     jurnal = await jason_save(file='CONTEINERS_RF', open_file=True)
#     answer_list = '<b>Журнал реф техника:</b>\n====================================\n'
#     count_ref = jurnal[-1]['LineNumber']
#     count = len([item for item in jurnal if item.get('ДатаОсмотра') != "0001-01-01T00:00:00"])  # Количество осмотренных контейнеров
#     completion_percentage = (count / int(count_ref)) * 100
#     answer_list += f'<b>Текущий журнал реф техника\nвыполнен на: {completion_percentage:.2f}%</b>\n\n<b>{await curent_date()}</b>'
#     return answer_list


async def text_to_new_jurn():
    jurnal = await jason_save(file='REF_JURNAL', open_file=True)
    answer_list = '<b>Журнал реф техника:</b>\n====================================\n'
    count_ref = jurnal['колличество']
    count = jurnal['осмотренные']  # Количество осмотренных контейнеров
    completion_percentage = (count / int(count_ref)) * 100
    answer_list += f'<b>Текущий журнал реф техника\nвыполнен на: {completion_percentage:.2f}%</b>\n\n<b>{await curent_date()}</b>'
    return answer_list


#@router.message(F.text == 'Журнал обходов', canceling2)
#async def select_jur(message: Message, state: FSMContext):
    #await message.delete()
    #ic('Журнал обходов сработал')         #new_jur=False update_jur=True

    #await message.bot.send_chat_action(message.chat.id, 'typing')
    #await asyncio.sleep(0.1)
    #await state.set_state(Jrnal.one)
    #answer_list = await text_to_new_jurn()

    #await message.answer(answer_list, reply_markup=select_jurnal, parse_mode='HTML')


@router.callback_query(F.data == 'bypass_jurn')
async def select_jur(callback_query: types.CallbackQuery, state: FSMContext):
    await callback_query.message.delete()
    ic('Журнал обходов сработал')         #new_jur=False update_jur=True

    await callback_query.message.bot.send_chat_action(callback_query.message.chat.id, 'typing')
    await asyncio.sleep(0.1)
    await state.set_state(Jrnal.one)
    answer_list = await text_to_new_jurn()

    await callback_query.message.answer(answer_list, reply_markup=select_jurnal, parse_mode='HTML')


# Новый способ через API
@router.callback_query(F.data == 'one_jurnal')
async def number_cont_in(callback_query: types.CallbackQuery, state: FSMContext):
    global back_gps_key
    # await callback_query.message.delete()
    # posted_gps = await process_bac(update_jur=True)
    posted_gps = asyncio.create_task(process_bac(update_jur=True))
    posted_gps = await posted_gps
    answer_list = '<b>Журнал реф техника:</b>\n====================================\n'
    count_ref = posted_gps['колличество']
    count = posted_gps['осмотренные']
    answer_list += f'<b>Общее количество контейнеров: {count_ref}</b>\nОсмотренных: {count}\nНеосмотренных: {int(count_ref) - count}\n'

    exclude_keys = ['колличество', 'осмотренные', 'Дата', 'Номер']
    bottons2 = [types.InlineKeyboardButton(text=key, callback_data='Cont_gps_' + key) for key in posted_gps.keys() if key not in exclude_keys]
    inline_keyboard21 = [bottons2[i:i + 2] for i in range(0, len(bottons2), 2)]
    bottons3 = [types.InlineKeyboardButton(text='отмена', callback_data='one_jur_back')]
    inline_keyboard21.append(bottons3)
    inline_keyboard3 = InlineKeyboardMarkup(inline_keyboard=inline_keyboard21)
    back_gps_key = inline_keyboard3
    await callback_query.message.bot.send_chat_action(callback_query.message.chat.id, 'typing')
    await state.set_data(posted_gps)
    await state.set_state(Jrnal.two)
    await callback_query.message.edit_text(answer_list, reply_markup=inline_keyboard3, parse_mode='HTML')


@router.callback_query(F.data.startswith('Cont_gps_'))
async def number_cont_in(callback_query: types.CallbackQuery, state: FSMContext):
    # await callback_query.message.delete()
    dict_ = await state.get_data()
    data_text = callback_query.data.split('_')
    await asyncio.sleep(0.1)
    container_list = [
        f'<b>{value["LineNumber"]}|  {str(key)}</b>  <i>{value["gps"].replace("  ", " ").split("; ")[-1]}  {" " if value["ДатаОсмотра"] == "0001-01-01T00:00:00" else "✅"}</i>'\
        for key, value in dict_[data_text[2]].items()
    ]
    answer_list = f'<b>Журнал реф техника:</b>\n{data_text[-1]}\n====================================\n'
    answer_list += '\n'.join(container_list)

    bottons = [types.InlineKeyboardButton(text=str(value['num']), callback_data='Cont_ref_' + str(key)) for key, value in dict_[data_text[2]].items()]
    # for value in dict_[data_text[2]]:
    #     bottons.append([])
    #
    inline_keyboard = [bottons[i:i + 8] for i in range(0, len(bottons), 8)]
    bottons2 = [types.InlineKeyboardButton(text='Назад', callback_data='one_gps_back')]
    inline_keyboard.append(bottons2)
    inline_keyboard2 = InlineKeyboardMarkup(inline_keyboard=inline_keyboard)
    await callback_query.message.bot.send_chat_action(callback_query.message.chat.id, 'typing')
    await state.set_data(dict_[data_text[2]])
    await state.set_state(Jrnal.two)
    await callback_query.message.edit_text(answer_list, reply_markup=inline_keyboard2, parse_mode='HTML')


@router.callback_query(F.data == 'new_jurnyl')
async def number_cont_in(callback_query: types.CallbackQuery, state: FSMContext):
    await callback_query.message.bot.send_chat_action(callback_query.message.chat.id, 'typing')
    await asyncio.sleep(0.1)
    await process_bac(AUTHORS[callback_query.from_user.id], new_jur=True)
    await state.clear()
    await callback_query.message.bot.send_chat_action(callback_query.message.chat.id, 'typing')
    await callback_query.message.edit_text('Новый журнал загружен.\nВыберите журнал', reply_markup=select_jurnal)


async def Get_inspect_det(callback_query: types.CallbackQuery, state: FSMContext):
    ic(callback_query.data)
    text = callback_query.data

    if text.startswith('Cont_ref_'):
        await get_cont_ref(callback_query, state)
    elif text == 'jr_photo_ref':
        return True
    elif text in ['jr_edit_temp', 'js_temp', 'js_minus_temp', 'js_plus_temp', 'js_minus_temp-0.1',
                               'js_plus_temp-0.1', 'js_save_temp', 'jr_erorrs_ref', 'connect', 'js_cancel_ref',
                               'js_cancel', 'save_data', 'js_save_data', 'go_back', 'one_jur_back', 'one_gps_back',]:
        return True
    elif text == 'canceling_rj':
        await vision_conteiners_rf(callback_query, state, ref_jr_control, edit=True)


async def get_cont_ref(callback_query: types.CallbackQuery, state: FSMContext):
    text = callback_query.data
    dict_ = await state.get_data()
    ic(dict_)
    data = dict_
    cont_number = text.split('_')[2]
    cont_data = data[cont_number]
    ref_key = cont_data['Ref_Key']
    cont = http_rest.ContainerInfo()
    cont.RefKey = cont_data['Контейнер_Key']
    cont.ContNum = cont_number
    date_conteiner = await cont.FillContainerInfo()
    cont_data['Status'] = date_conteiner['Status']
    await state.set_data(cont_data)
    await state.set_state(Jrnal.temp2)
    await callback_query.message.bot.send_chat_action(callback_query.message.chat.id, 'typing')
    await vision_conteiners_rf(callback_query, state, ref_jr_control, edit=True)


@router.callback_query(Get_inspect_det)
async def get_inspect(callback_query: types.Update, state: FSMContext):
    text = callback_query.data
    dict_ = await state.get_data()
    data = dict_
    await asyncio.sleep(.1)
    # await callback_query.message.delete()
    if callback_query.data == 'jr_edit_temp':
        dict_['NewTemp'] = dict_['НормативнаяT']
        await state.set_data(dict_)

        await vision_conteiners_rf(callback_query, state, js_ref_temp, edit=True)
    elif callback_query.data == 'js_temp':
        # await callback_query.message.delete()
        await state.set_state(Jrnal.temp2)
        bot_message = await callback_query.message.edit_text('Укажите температуру', reply_markup=js_ref_opt)
        dict_['message_id'] = bot_message.message_id
        await state.set_data(dict_)
    elif callback_query.data == 'js_minus_temp':
        if data.get('NewTemp') is None:
            data['NewTemp'] = str(float(data['НормативнаяT']) + 1)
        data['NewTemp'] = str(round(float(data['NewTemp']) - 1, 2))
        await state.set_data(data)
        await vision_conteiners_rf(callback_query, state, js_ref_temp, edit=True)
    elif callback_query.data == 'js_plus_temp':
        if data.get('NewTemp') is None:
            data['NewTemp'] = str(float(data['НормативнаяT']) - 1)
        data['NewTemp'] = str(round(float(data['NewTemp']) + 1, 2))
        await state.set_data(data)
        await vision_conteiners_rf(callback_query, state, js_ref_temp, edit=True)
    elif callback_query.data == 'js_minus_temp-0.1':
        if data.get('NewTemp') is None:
            data['NewTemp'] = str(float(data['НормативнаяT']) + 0.1)
        data['NewTemp'] = str(round(float(data['NewTemp']) - 0.1, 2))
        await state.set_data(data)
        await vision_conteiners_rf(callback_query, state, js_ref_temp, edit=True)
    elif callback_query.data == 'js_plus_temp-0.1':
        if data.get('NewTemp') is None:
            data['NewTemp'] = str(float(data['НормативнаяT']) - 0.1)
        data['NewTemp'] = str(round(float(data['NewTemp']) + 0.1, 2))
        await state.set_data(data)
        await vision_conteiners_rf(callback_query, state, js_ref_temp, edit=True)
    elif callback_query.data == 'js_cancel_ref':
        dict_['NewTemp'] = 'НЕТ'
        await state.set_data(dict_)
        await state.set_state(Jrnal.one)
        await vision_conteiners_rf(callback_query, state, ref_jr_control, edit=True)
    elif callback_query.data == 'js_cancel':
        await state.clear()
        answer_list = await text_to_new_jurn()
        await callback_query.message.edit_text(answer_list, reply_markup=select_jurnal, parse_mode='HTML')
        # await vision_conteiners_rf(callback_query, state, select_jurnal, edit=True)
    elif callback_query.data == 'jr_erorrs_ref':
        # await callback_query.message.delete()
        await state.set_state(Jrnal.err_2)
        bot_message = await callback_query.message.edit_text('Укажите ошибки', reply_markup=js_ref_opt)
        dict_['message_id'] = bot_message.message_id
        await state.set_data(dict_)
    elif callback_query.data == 'jr_photo_ref':
        # await callback_query.message.delete()
        await state.set_state(Jrnal.photo_cont)
        bot_message = await callback_query.message.edit_text('Загрузите фото', reply_markup=js_ref_opt)
        dict_['message_id'] = bot_message.message_id
        await state.set_data(dict_)
    elif callback_query.data == 'js_save_temp':
        await state.set_state(Jrnal.one)
        await vision_conteiners_rf(callback_query, state, ref_jr_control, edit=True)
    elif callback_query.data == 'js_save_data':
        await state.set_state(Jrnal.one)
        await vision_conteiners_rf(callback_query, state, select_jurnal, send=True, edit=True)
    elif callback_query.data == 'go_back':
        ic('Go backk')
        await callback_query.message.delete()
        await state.clear()
        await callback_query.message.answer('Выберите действие', reply_markup=tech_actions)
    elif callback_query.data == 'one_jur_back':
        answer_list = await text_to_new_jurn()
        await callback_query.message.edit_text(answer_list, reply_markup=select_jurnal, parse_mode='HTML')
    elif callback_query.data == 'one_gps_back':
        # global back_gps_key
        await state.clear()
        answer_list = await text_to_new_jurn()
        await callback_query.message.edit_text(answer_list, reply_markup=select_jurnal, parse_mode='HTML')


async def is_temperature2(message: Message, state: FSMContext):
    pattern = re.compile(r'^-?\d+(\.\d+)?$')
    if pattern.match(str(message.text)):
        return True
    elif message.text == 'cancel_ref':
        await state.set_state(Jrnal.one)
        await vision_conteiners_rf(message, state, ref_jr_control)
    elif message.text == 'Отмена':
        await message.bot.delete_message(message.chat.id, message.message_id)

        await vision_conteiners_rf(message, state, js_ref_temp)
    else:
        await state.set_state(Jrnal.temp2)
        await message.answer('Введены не корректные данные тепературы')
        return False


@router.message(Jrnal.photo_cont)
async def ref_mon_img(message: Message, state: FSMContext):
    dict_ = await state.get_data()

    if message.photo:
        await message.bot.delete_message(message.chat.id, dict_['message_id'])
        ic('Загружаем фото')
        dict_ = await state.get_data()
        photo = message.photo[-1].file_id
        dates = await curent_date()
        time, date = dates.split()
        num_jurn = dict_['doc_num']

        if 20 < int(time.split(':')[0]) or int(time.split(':')[0]) < 8:
            change_user = 'C2'
        else:
            change_user = 'C1'
        folder_path = f'{date}/{change_user}/{num_jurn}'
        if not os.path.exists(folder_path):
            os.makedirs(folder_path, exist_ok=True)

        file_path = f'{folder_path}/{date.replace(".", "-")}_{time.replace(":", "-")}_{dict_["ContNum"]}_{photo[13:20]}.jpg'
        ic(file_path)
        if dict_.get('ref_mon_img') is None:
            dict_['ref_mon_img'] = []
        dict_['ref_mon_img'].append(file_path)
        await state.set_data(dict_)
        await message.bot.download(file=photo, destination=file_path)
        await state.set_state(Jrnal.one)
        await message.bot.delete_message(message.chat.id, message.message_id)
        await vision_conteiners_rf(message, state, ref_jr_control)
    else:
        await message.bot.delete_message(message.chat.id, message.message_id)
        await state.set_state(Jrnal.photo_cont)
        bot_message = await message.answer('Нужно загрузить фото', reply_markup=js_ref_opt)
        await asyncio.sleep(10)
        await bot_message.delete()


@router.message(Jrnal.temp2, is_temperature2)
async def add_temp2(message: Message, state: FSMContext):
    dict_ = await state.get_data()
    await message.bot.delete_message(message.chat.id, dict_['message_id'])
    dict_['NewTemp'] = message.text
    await state.set_data(dict_)
    await message.bot.delete_message(message.chat.id, message.message_id)
    await vision_conteiners_rf(message, state, js_ref_temp)


@router.message(Jrnal.err_2, canceling2)
async def ref_mon_errors(message: Message, state: FSMContext):
    await message.delete()
    dict_ = await state.get_data()
    await message.bot.delete_message(message.chat.id, dict_['message_id'])
    dict_['NewErr'] = message.text
    await state.set_data(dict_)
    await state.set_state(Jrnal.one)
    # await message.answer('Изменения применены', reply_markup=None)
    await vision_conteiners_rf(message, state, ref_jr_control)


async def vision_conteiners_rf(message, state: FSMContext, ref_control: types.InlineKeyboardMarkup, send: bool = False, edit=False, options=None):
    dict_ = await state.get_data()
    CronFlag = False
    CronFlag2 = False
    Cont = http_rest.ContainerInfo()
    Cont.ContNum = dict_['ContNum']
    Cont.Cargo = dict_['Cargo']
    Cont.LastTemp = str(dict_['ФактическаяT'])
    Cont.ReqTemp = str(dict_['НормативнаяT'])
    Cont.NewTemp = str(dict_['NewTemp']) if dict_.get('NewTemp') is not None else '0'
    Cont.NewErr = dict_.get('NewErr') if dict_.get('NewErr') is not None else ''
    Cont.LastErr = dict_['Lasterr']
    Cont.LastViev = dict_['ДатаОсмотра']
    Cont.Status = dict_['Status']
    Cont.StatusDate = await curent_date()
    Cont.LastGPS = dict_['gps']
    Cont.RefJournalNum = dict_['Ref_Key']


    if send:
        DocNum = dict_['doc_num']

        ContNumberRefKey = dict_['Контейнер_Key']

        Tfact = dict_.get('NewTemp') if dict_.get('NewTemp') is not None else ic(Cont.ReqTemp)
        Alarm = dict_.get('NewErr') if dict_.get('NewErr') is not None else ''
        text_request = {
            "filter": "Number eq `" + DocNum + "`"}
        request = await http_rest.send_odata_get("Document_ЖурналОбходовРефов",
                                           text_request)
        data_2 = request.json()

        now = datetime.now()
        if len(Cont.LastErr) > 0 and Cont.LastErr not in ['', None, 'НЕТ', '0'] and Cont.NewErr not in ['', None, 'НЕТ', '0']:
            Alarm = Cont.LastErr.replace(', , ', '') + ', ' + Cont.NewErr
        elif Cont.NewErr not in ['', None, 'НЕТ', '0']:
            Alarm = Cont.NewErr
        long_text = {'Контейнеры': []}
        # response = await http_rest.sender_to_1c(Cont.RefJournalNum, ContNumberRefKey, Tfact, Alarm)
        # ic(response)
        for i in range(len(data_2['value'][0]['Контейнеры'])):
            if data_2['value'][0]['Контейнеры'][i]['Контейнер_Key'] == ContNumberRefKey:
                data_2['value'][0]['Контейнеры'][i]['Контейнер_Key'] = ContNumberRefKey
                data_2['value'][0]['Контейнеры'][i]['ДатаОсмотра'] = str(now.strftime("%Y-%m-%dT%H:%M:%S"))
                data_2['value'][0]['Контейнеры'][i]['МестоРазмещения'] = Cont.LastGPS
                data_2['value'][0]['Контейнеры'][i]['НормативнаяT'] = Cont.ReqTemp
                data_2['value'][0]['Контейнеры'][i]['ФактическаяT'] = Cont.NewTemp if Cont.NewTemp not in ['', None, 'НЕТ', '0'] else Cont.LastTemp
                data_2['value'][0]['Контейнеры'][i]['Alarm'] = Alarm
                data_2['value'][0]['Контейнеры'][i]['Груз'] = Cont.Cargo
            long_text['Контейнеры'].append(
                {
                    'Ref_Key': data_2['value'][0]['Ref_Key'],
                    'LineNumber': str(data_2['value'][0]['Контейнеры'][i]['LineNumber']),
                    'Контейнер_Key': str(data_2['value'][0]['Контейнеры'][i]['Контейнер_Key']),
                    'МестоРазмещения': str(data_2['value'][0]['Контейнеры'][i]['МестоРазмещения']),
                    'НормативнаяT': str(data_2['value'][0]['Контейнеры'][i]['НормативнаяT']),
                    'ФактическаяT': str(data_2['value'][0]['Контейнеры'][i]['ФактическаяT']),
                    'Alarm': str(data_2['value'][0]['Контейнеры'][i]['Alarm']),
                    'Груз': str(data_2['value'][0]['Контейнеры'][i]['Груз']),
                    'ДатаОсмотра': data_2['value'][0]['Контейнеры'][i]['ДатаОсмотра']}
            )

        async with semaphore:
            update_req = await http_rest.send_odata_patch(
                'Document_ЖурналОбходовРефов(guid`' + data_2['value'][0]['Ref_Key'] + '`)', long_text)
        if update_req.status_code in [200, 201, 204]:
            await state.clear()
            answer_list = await text_to_new_jurn()
            await message.message.edit_text(answer_list,
                                         reply_markup=select_jurnal, parse_mode='HTML')
        else:
            await message.answer('Состояние реф контейнера не обновлено', reply_markup=select_jurnal)
    elif edit:
        if not not options:
            await state.set_state(options)
        await message.message.edit_text(
            text=Cont.PrintHtml(), reply_markup=ref_control, parse_mode='HTML')
    elif type(message) == types.CallbackQuery:
        if not not options:
            await state.set_state(options)
        # await message.message.delete()
        await message.message.answer(
            text=Cont.PrintHtml(), reply_markup=ref_control, parse_mode='HTML')
    else:
        if not not options:
            await state.set_state(options)
        await message.answer(
            text=Cont.PrintHtml(), reply_markup=ref_control, parse_mode='HTML')
